home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Risc World 3
/
Risc World 3.iso
/
SOFTWARE
/
ISSUE6
/
PD
/
PDF
/
pdf
/
c++
/
DrawOutputFont
< prev
next >
Wrap
Text File
|
2003-02-17
|
13KB
|
444 lines
//--------------------------------------------------------------------------
//
// Copyright (c) 2002, Colin Granville
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted provided that the following
// conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// * The name Colin Granville may not be used to endorse or promote
// products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//
//--------------------------------------------------------------------------
#include "DrawOutputFont.h"
#include "GfxFont.h"
#include "GfxState.h"
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#include "ucompare.h"
#include <iostream.h>
#include "PdfDocEncoding.h"
#include "GlobalParams.h"
#include "iostream.h"
#include "FontEncodingTables.h"
#define DEFAULT_FONT_LIST_SIZE 14
double charWidths[DEFAULT_FONT_LIST_SIZE][256];
struct FontFace
{
const char* pdfName;
const char* riscOsName;
UnicodeToAcornMap* map;
double* charWidth;
} defaultFonts[DEFAULT_FONT_LIST_SIZE] = {
{"Courier", "Corpus.Medium", 0, charWidths[0]},
{"Courier-Bold", "Corpus.Bold", 0, charWidths[1]},
{"Courier-Oblique", "Corpus.Medium.Oblique", 0, charWidths[2]},
{"Courier-BoldOblique", "Corpus.Bold.Oblique", 0, charWidths[3]},
{"Helvetica", "Homerton.Medium", 0, charWidths[4]},
{"Helvetica-Bold", "Homerton.Bold", 0, charWidths[5]},
{"Helvetica-Oblique", "Homerton.Medium.Oblique", 0, charWidths[6]},
{"Helvetica-BoldOblique", "Homerton.Bold.Oblique", 0, charWidths[7]},
{"Times-Roman", "Trinity.Medium", 0, charWidths[8]},
{"Times-Bold", "Trinity.Bold", 0, charWidths[9]},
{"Times-Italic", "Trinity.Medium.Italic", 0, charWidths[10]},
{"Times-BoldItalic", "Trinity.Bold.Italic", 0, charWidths[11]},
{"Symbol", "Sidney", 0, charWidths[12]},
{"ZapfDingbats", "Selwyn", 0, charWidths[13]}
};
class InitDefaultFonts
{
public:
UnicodeToAcornMap latin1;
UnicodeToAcornMap symbol;
UnicodeToAcornMap dingbats;
InitDefaultFonts();
} initDefaultFonts;
InitDefaultFonts::InitDefaultFonts()
: latin1(unicodeToAcornLatin1),
symbol(unicodeToAcornSymbol),
dingbats(unicodeToAcornDingbats)
{
int f;
for (f=0;f<DEFAULT_FONT_LIST_SIZE;f++)
{
if (f==DEFAULT_FONT_LIST_SIZE-1) defaultFonts[f].map=&dingbats;
else if (f==DEFAULT_FONT_LIST_SIZE-2) defaultFonts[f].map=&symbol;
else defaultFonts[f].map=&latin1;
}
for (f=0;f<DEFAULT_FONT_LIST_SIZE;f++)
{
int handle=0;
_swix(Font_FindFont,_INR(1,5) | _OUT(0), defaultFonts[f].riscOsName,16,16,0,0,&handle);
if (handle)
{
int spacewidth=0;
_swix(Font_ScanString,_INR(0,5) | _OUT(3), 0," ",0,-1,-1,0,&spacewidth);
int i;
for (i=0;i<32;i++) charWidths[f][i]=0;
char s[4];
s[0]=' ';s[2]=' ';s[3]=0;
for (i=32;i<256;i++)
{
int size=spacewidth;
s[1]=i;
_swix(Font_ScanString,_INR(0,5) | _OUT(3), 0,s,0,-1,-1,0,&size);
charWidths[f][i]=double(size-spacewidth)/1000.0;
}
if (f<DEFAULT_FONT_LIST_SIZE-2) charWidths[f][0x8f]=0;//dont alter shape of bullet
_swix(Font_LoseFont,_IN(0),handle);
}
}
}
//*****************************************************************
//*****************************************************************
//*****************************************************************
DrawOutputFontList::DrawOutputFontList()
: fontList(0),
handle(0)
{
flags=0;
}
//*****************************************************************
DrawOutputFontList::~DrawOutputFontList() {clear();}
//*****************************************************************
void DrawOutputFontList::declareFonts()
{
int i;
for (i=0;i<DEFAULT_FONT_LIST_SIZE;i++)
{
_swix(PDriver_DeclareFont,_INR(0,2),0,defaultFonts[i].riscOsName,0);
}
}
//*****************************************************************
const char* DrawOutputFontList::getUsedFont(int fontIndex)
{
fontIndex--;
if (fontIndex<0 || fontIndex>=DEFAULT_FONT_LIST_SIZE) return 0;
return defaultFonts[fontIndex].riscOsName;
}
//*****************************************************************
void DrawOutputFontList::clear()
{
lose();
DrawOutputFont* f=fontList;
DrawOutputFont* next=0;
for (;f;f=next) {next=f->next;delete f;}
fontList=0;
}
//*****************************************************************
void DrawOutputFontList::atExit()
{
lose();
}
//*****************************************************************
void DrawOutputFontList::find(GfxState& state)
{
if (fontList==0) return;
double fontsize=(state.getFont() ? state.getFontSize() : 10.0);
int newFontXSize= int(fontsize*matXScale*state.getHorizScaling()) ;
if (newFontXSize<40) newFontXSize=40; //causes redraw problems if size < 1/16 pt
int newFontYSize= (int)(fontsize*matYScale);
if (newFontYSize<40) newFontYSize=40; //causes redraw problems if size < 1/16 pt
if (font==fontList->getFontIndex() && newFontYSize==fontYSize && newFontXSize==fontXSize) return;
fontXSize=newFontXSize;
fontYSize=newFontYSize;
font=fontList->getFontIndex();
int oldhandle=handle;
_swix(Font_FindFont,_INR(1,5) | _OUT(0), fontList->getRiscOsFontName(),
fontXSize/40,
fontYSize/40,
0,
0,
&handle);
if (oldhandle) _swix(Font_LoseFont,_IN(0),oldhandle);
}
//*****************************************************************
void DrawOutputFontList::lose()
{
if (handle)
{
_swix(Font_LoseFont,_IN(0),handle);
handle=0;
}
}
//*****************************************************************
void DrawOutputFontList::setMatrix(GfxState& state)
{
double* ctm=state.getCTM();
double* tm=state.getTextMat();
//calculate x scale
double a = tm[0]*ctm[0] + tm[1]*ctm[2];
double b = tm[0]*ctm[1] + tm[1]*ctm[3];
double scale = sqrt(a*a+b*b);
charMatrix[0]=(a*65536.0/scale);
transform.m0 = (int)charMatrix[0];
charMatrix[1]=(b*65536.0/scale);
transform.m1 = (int)charMatrix[1];
matXScale=scale;
//calculate y scale
a=tm[2]*ctm[0] + tm[3]*ctm[2];
b=tm[2]*ctm[1] + tm[3]*ctm[3];
scale=sqrt(a*a+b*b);
transform.m2 = (int)(a*65536.0/scale);
transform.m3 = (int)(b*65536.0/scale);
matYScale=scale;
}
//*****************************************************************
void DrawOutputFontList::setCharMatrix(double fromWid, double toWid)
{
double scale= (fromWid!=0 && toWid !=0 ? fromWid/toWid :1.0);
transform.m0=(int)(charMatrix[0]*scale);
transform.m1=(int)(charMatrix[1]*scale);
}
//*****************************************************************
void DrawOutputFontList::set(GfxState& state)
{
setMatrix(state);
GfxFont* gfxFont=state.getFont();
DrawOutputFont* f=fontList;
DrawOutputFont* last=0;
for (;f;last=f,f=f->next)
{
if (gfxFont==f->getFont())
{
if (last)
{
last->next=f->next;
f->next=fontList;
fontList=f;
}
find(state);
return;
}
}
f=new DrawOutputFont(gfxFont);
if (f)
{
f->next=fontList;
fontList=f;
find(state);
}
}
//*****************************************************************
//*****************************************************************
//*****************************************************************
DrawOutputFont::DrawOutputFont(GfxFont* gfxFont)
: font(gfxFont),
mapStore(0)
{
if (!gfxFont)
{
getSubstituteFont(0);
return;
}
GString*font_name=gfxFont->getName();
if (!font_name) font_name = gfxFont->getEmbeddedFontName();
if (!font_name || !findFont(font_name->getCString()))
{
getSubstituteFont(font_name?font_name->getCString():0);
}
return;
}
//*****************************************************************
DrawOutputFont::~DrawOutputFont()
{
delete mapStore;
}
//*****************************************************************
void DrawOutputFont::getSubstituteFont(const char* name)
{
if (font==0)
{
riscOsFontName=defaultFonts[0].riscOsName;
map=defaultFonts[0].map;
charWidth=defaultFonts[0].charWidth;
fontIndex=1;
return;
}
int i=4;
if (name)
{
if (font->isSerif() ||
uFind(name,"times") ||
(!uFind(name,"sans") && uFind(name,"serif")) ||
uFind(name,"Garamond")) i=8;
if (font->isFixedWidth() || uFind(name,"courier")) i=0;
if (font->isItalic() || uFind(name,"obli") || uFind(name,"ital") ) i|=2;
if (font->isBold() || uFind(name,"bold")|| uFind(name,"black")) i|=1;
}
else i=8;//serif font
map=defaultFonts[i].map;
riscOsFontName=defaultFonts[i].riscOsName;
charWidth=defaultFonts[i].charWidth;
fontIndex=i+1;
}
//*****************************************************************
bool DrawOutputFont::findFont(const char* name)
{
if (name==0) return 0;
const char* n=name;
while (!(*n==0 || *n=='+' || *n=='-')) n++;
if (*n=='+') name=n+1;
int i;
for (i=0;i<DEFAULT_FONT_LIST_SIZE;i++)
{
if (uCompare(name,defaultFonts[i].pdfName)==0)
{
riscOsFontName=defaultFonts[i].riscOsName;
map=defaultFonts[i].map;
charWidth=defaultFonts[i].charWidth;
fontIndex=i+1;
return 1;
}
}
return 0;
}
//*****************************************************************
//*****************************************************************
//*****************************************************************
class StandardFontToAcornLatin1
{
public:
StandardFontToAcornLatin1();
unsigned char getChar(const unsigned char c) {return map[c];}
private:
unsigned char map[256];
};
StandardFontToAcornLatin1& standardFontToAcornLatin1()
{
static StandardFontToAcornLatin1 p;
return p;
}
//*****************************************************************
StandardFontToAcornLatin1::StandardFontToAcornLatin1()
{
for (int i=0;i<256;i++)
{
map[i]=0;
char* name=pdfDocEncoding[i];
if (name)
{
Unicode u=globalParams->mapNameToUnicode(name);
if (u) map[i]=initDefaultFonts.latin1.getChar(u);
}
}
}
//*****************************************************************
string toAcornLatin1(const char* str, int len)
{
string res;
unsigned char* p=(unsigned char*)str;
if (p[0]==0xfe && p[1]==0xff)
{
res.reserve(len/2);
for (int i=2;i<len;i+=2)
{
unsigned char c=initDefaultFonts.latin1.getChar(p[i]+p[i+1]*256);
if (c!=UnicodeToAcornMap::NO_CONVERSION_CHAR) res+=c;
}
}
else if (p[0]==0xff && p[1]==0xfe)
{
res.reserve(len/2);
for (int i=2;i<len;i+=2)
{
unsigned char c=initDefaultFonts.latin1.getChar(p[i+1]+p[i]*256);
if (c!=UnicodeToAcornMap::NO_CONVERSION_CHAR) res+=c;
}
}
else
{
StandardFontToAcornLatin1& s = standardFontToAcornLatin1();
res.reserve(len);
for (int i=0;i<len;i++)
{
unsigned char c = s.getChar(p[i]);
if (c) res+=(char)c;
}
}
return res;
}